package utils

import (
	"bookmark-web/models"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"regexp"
	"strings"
	"time"
)

// GetURLPreview 获取网址预览信息（标题和图标）
func GetURLPreview(targetURL string) (*models.BookmarkPreviewResponse, error) {
	// 验证URL格式
	parsedURL, err := url.Parse(targetURL)
	if err != nil {
		return nil, fmt.Errorf("无效的URL格式: %v", err)
	}

	// 确保URL有协议
	if parsedURL.Scheme == "" {
		targetURL = "https://" + targetURL
		parsedURL, err = url.Parse(targetURL)
		if err != nil {
			return nil, fmt.Errorf("无效的URL格式: %v", err)
		}
	}

	// 创建HTTP客户端，设置超时
	client := &http.Client{
		Timeout: 10 * time.Second,
	}

	// 发送HTTP请求
	req, err := http.NewRequest("GET", targetURL, nil)
	if err != nil {
		return nil, fmt.Errorf("创建请求失败: %v", err)
	}

	// 设置User-Agent，避免被某些网站拒绝
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")

	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("请求失败: %v", err)
	}
	defer resp.Body.Close()

	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP错误: %d", resp.StatusCode)
	}

	// 读取响应内容
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取响应失败: %v", err)
	}

	html := string(body)

	// 提取标题和图标
	title := extractTitle(html)
	favicon := extractFavicon(html, parsedURL)

	// 如果没有提取到标题，使用域名作为标题
	if title == "" {
		title = parsedURL.Host
	}

	return &models.BookmarkPreviewResponse{
		Title:   title,
		Favicon: favicon,
		URL:     targetURL,
	}, nil
}

// extractTitle 从HTML中提取标题
func extractTitle(html string) string {
	// 匹配<title>标签
	titleRegex := regexp.MustCompile(`<title[^>]*>([^<]*)</title>`)
	matches := titleRegex.FindStringSubmatch(html)
	if len(matches) > 1 {
		title := strings.TrimSpace(matches[1])
		// 解码HTML实体
		title = decodeHTMLEntities(title)
		return title
	}

	// 尝试匹配og:title
	ogTitleRegex := regexp.MustCompile(`<meta[^>]*property=["\']og:title["\'][^>]*content=["\']([^"\']*)["\']`)
	matches = ogTitleRegex.FindStringSubmatch(html)
	if len(matches) > 1 {
		return strings.TrimSpace(matches[1])
	}

	return ""
}

// extractFavicon 从HTML中提取网站图标
func extractFavicon(html string, baseURL *url.URL) string {
	// 常见的favicon链接模式
	patterns := []string{
		`<link[^>]*rel=["\']icon["\'][^>]*href=["\']([^"\']*)["\']`,
		`<link[^>]*rel=["\']shortcut icon["\'][^>]*href=["\']([^"\']*)["\']`,
		`<link[^>]*href=["\']([^"\']*)["\'][^>]*rel=["\']icon["\']`,
		`<link[^>]*href=["\']([^"\']*)["\'][^>]*rel=["\']shortcut icon["\']`,
	}

	for _, pattern := range patterns {
		regex := regexp.MustCompile(pattern)
		matches := regex.FindStringSubmatch(html)
		if len(matches) > 1 {
			faviconURL := strings.TrimSpace(matches[1])
			return resolveURL(faviconURL, baseURL)
		}
	}

	// 如果没有找到，尝试默认的favicon.ico
	return fmt.Sprintf("%s://%s/favicon.ico", baseURL.Scheme, baseURL.Host)
}

// resolveURL 解析相对URL为绝对URL
func resolveURL(href string, baseURL *url.URL) string {
	if href == "" {
		return ""
	}

	// 如果已经是绝对URL，直接返回
	if strings.HasPrefix(href, "http://") || strings.HasPrefix(href, "https://") {
		return href
	}

	// 如果是协议相对URL（//example.com/favicon.ico）
	if strings.HasPrefix(href, "//") {
		return baseURL.Scheme + ":" + href
	}

	// 如果是绝对路径（/favicon.ico）
	if strings.HasPrefix(href, "/") {
		return fmt.Sprintf("%s://%s%s", baseURL.Scheme, baseURL.Host, href)
	}

	// 相对路径，拼接到base URL
	return fmt.Sprintf("%s://%s/%s", baseURL.Scheme, baseURL.Host, href)
}

// decodeHTMLEntities 简单的HTML实体解码
func decodeHTMLEntities(s string) string {
	replacements := map[string]string{
		"&amp;":  "&",
		"&lt;":   "<",
		"&gt;":   ">",
		"&quot;": "\"",
		"&#39;":  "'",
		"&nbsp;": " ",
	}

	for entity, replacement := range replacements {
		s = strings.ReplaceAll(s, entity, replacement)
	}

	return s
}

// ValidateURL 验证URL格式
func ValidateURL(targetURL string) error {
	if targetURL == "" {
		return fmt.Errorf("URL不能为空")
	}

	// 如果没有协议，添加https://
	if !strings.HasPrefix(targetURL, "http://") && !strings.HasPrefix(targetURL, "https://") {
		targetURL = "https://" + targetURL
	}

	_, err := url.Parse(targetURL)
	// Parse 函数作用：解析URL字符串，返回一个URL对象
	if err != nil {
		return fmt.Errorf("无效的URL格式: %v", err)
	}

	return nil
}

// NormalizeURL 标准化URL格式
func NormalizeURL(targetURL string) string {
	if targetURL == "" {
		return ""
	}

	// 如果没有协议，添加https://
	if !strings.HasPrefix(targetURL, "http://") && !strings.HasPrefix(targetURL, "https://") {
		targetURL = "https://" + targetURL
	}

	// 移除末尾的斜杠
	targetURL = strings.TrimSuffix(targetURL, "/")
	// TrimSuffix 函数的作用是从字符串中移除指定的后缀

	return targetURL
}
